#include "channel.hpp"
#include "Task.hpp"
#include <string>
#include <unistd.h>
#include <vector>
#include <functional>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

enum
{
    OK = 0,
    UsageError,
    PipeError,
    ForkError
};

using work_t = function<void()>;

class processpool
{
public:
    processpool(int num, work_t w) : nums(num), work(w)
    {
    }

    int Initprocesspool()
    {
        // 依次初始化
        for (int i = 0; i < nums; i++)
        {
            int piparr[2] = {0};
            int pd = pipe(piparr);

            if (pd < 0)
                return PipeError;

            int pid = fork();
            if (pid < 0)
                return ForkError;

            if (pid == 0)
            {
                for(auto&e:channels)
                {
                    //关闭之前创建的子进程的写端
                    e.Close();
                }
                close(piparr[1]);
                // 将管道重定向，让它在键盘直接读
                dup2(piparr[0], 0);
                work();
                exit(1);
            }
            close(piparr[0]);
            //
            // 这里我们保存的写端管道的文件描述符
            channels.emplace_back(channel(piparr[1], pid));
        }
        return OK;
    }

    // 答应channel的信息
    void DebugPrint()
    {
        for (auto &e : channels)
        {
            cout << e.Name() << endl;
        }
    }

    void DispathcTask()
    {

        // 指定有多少个任务
        int num = 10;
        int who = 0;
        while (num--)
        {
            // 选择一个任务
            int task = tes.SeletTask();
            //
            channel &cur = channels[who++];
            who %= channels.size();
            // 父进程发送任务
            cout << "###########################" << endl;
            // 打印发送任务给哪个子进程
            cout << "send" << task << cur.Name() << "任务还剩" << num << "个" << endl;
            cout << "###########################" << endl;
            cur.Send(task);
            sleep(2);
        }
    }
    void Exit()
    {
        for (auto &e : channels)
        {
            //关闭自己写段的通道，一个一个等待子进程
            e.Close();
            pid_t rid = waitpid(e.Id(), nullptr, 0);
            if (rid > 0)
            {
                cout << "子进程:" << rid << "退出成功" << endl;
            }
        }
    }

private:
    vector<channel> channels;
    int nums;
    work_t work;
};